package gui;

import io.hd.GestorLog;
import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Image;
import java.awt.SystemTray;
import java.awt.TrayIcon;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Calendar;
import java.util.List;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileFilter;
import logica.Nucleo;
import logica.NucleoListener;

/**
 *
 * @author Mariano Zapata
 */
public class Ventana extends javax.swing.JFrame implements NucleoListener {

    private Nucleo nucleo;
    private PanelPrincipal pp;
    private SystemTray barraNotificacion;
    private TrayIcon iconoBarraNotificacion;
    
    private static final String DETENER_NO= "No se puede detener el Servidor porque hay conexiones activas.";
    private static final String MINIMIZAR_AN_NO= "El área de notificación no es soportada por su Sistema Operativo.";
    private static final String MINIMIZAR_AN_FALLO= "No se pudo minimizar al área de notificación. Vuelva a intentarlo.";
    private static final String REINICIAR= "Parámetros de configuración guardados.\nEl Servidor debe ser reiniciado " +
            "para aplicar los cambios. Por favor vuelva a ejecutar la aplicación.";
    
    /** Creates new form Ventana */
    @SuppressWarnings("LeakingThisInConstructor")
    public Ventana(Nucleo nucleo) {
        initComponents();
        this.nucleo= nucleo;
        pp= new PanelPrincipal();
        Image icono= new ImageIcon(getClass().getResource("/gui/icono/logo_chico.png")).getImage();
        this.setIconImage(icono);
        this.getContentPane().setLayout(new BorderLayout());
        this.getContentPane().add(pp, BorderLayout.CENTER);
        this.pack();
        this.setLocationRelativeTo(null);
        barraNotificacion= null;
        iconoBarraNotificacion= new TrayIcon(icono, "", menuBarraTray);
        this.nucleo.agregarNucleoListener(this);
        MouseListener escuchaRaton= new MouseListener() {

            @Override
            public void mouseClicked(MouseEvent e) {clickRaton(e);}

            @Override
            public void mousePressed(MouseEvent e) {/*NO*/}

            @Override
            public void mouseReleased(MouseEvent e) {/*NO*/}

            @Override
            public void mouseEntered(MouseEvent e) {/*NO*/}

            @Override
            public void mouseExited(MouseEvent e) {/*NO*/}
            
        };
        iconoBarraNotificacion.setImageAutoSize(true);
        iconoBarraNotificacion.addMouseListener(escuchaRaton);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        menuBarraTray = new java.awt.PopupMenu();
        abrir = new java.awt.MenuItem();
        barraMenu = new javax.swing.JMenuBar();
        archivo = new javax.swing.JMenu();
        minimizarAN = new javax.swing.JMenuItem();
        configuracion = new javax.swing.JMenuItem();
        jSeparator1 = new javax.swing.JPopupMenu.Separator();
        acercaDe = new javax.swing.JMenuItem();
        jSeparator2 = new javax.swing.JPopupMenu.Separator();
        salir = new javax.swing.JMenuItem();
        respaldo = new javax.swing.JMenu();
        cargarRespaldo = new javax.swing.JMenuItem();
        crearRespaldo = new javax.swing.JMenuItem();

        menuBarraTray.setLabel("popupMenu1");

        abrir.setLabel("Abrir");
        abrir.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                abrir(evt);
            }
        });
        menuBarraTray.add(abrir);

        setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE);
        setTitle("Servidor - Estudio Jurídico");
        setResizable(false);
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                salirCruz(evt);
            }
        });

        archivo.setMnemonic('A');
        archivo.setText("Archivo");

        minimizarAN.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_M, java.awt.event.InputEvent.CTRL_MASK));
        minimizarAN.setText("Minimizar al área de notificación");
        minimizarAN.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                minimizarAN(evt);
            }
        });
        archivo.add(minimizarAN);

        configuracion.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_C, java.awt.event.InputEvent.CTRL_MASK));
        configuracion.setIcon(new javax.swing.ImageIcon(getClass().getResource("/gui/icono/configuracion.png"))); // NOI18N
        configuracion.setText("Configuración...");
        configuracion.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                configuracion(evt);
            }
        });
        archivo.add(configuracion);
        archivo.add(jSeparator1);

        acercaDe.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_A, java.awt.event.InputEvent.CTRL_MASK));
        acercaDe.setIcon(new javax.swing.ImageIcon(getClass().getResource("/gui/icono/acerca_de.png"))); // NOI18N
        acercaDe.setText("Acerca de...");
        acercaDe.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                acercaDe(evt);
            }
        });
        archivo.add(acercaDe);
        archivo.add(jSeparator2);

        salir.setText("Salir");
        salir.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                salir(evt);
            }
        });
        archivo.add(salir);

        barraMenu.add(archivo);

        respaldo.setMnemonic('R');
        respaldo.setText("Respaldo");

        cargarRespaldo.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_G, java.awt.event.InputEvent.CTRL_MASK));
        cargarRespaldo.setIcon(new javax.swing.ImageIcon(getClass().getResource("/gui/icono/respaldo_cargar.png"))); // NOI18N
        cargarRespaldo.setText("Cargar respaldo de datos...");
        cargarRespaldo.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cargarRespaldo(evt);
            }
        });
        respaldo.add(cargarRespaldo);

        crearRespaldo.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_R, java.awt.event.InputEvent.CTRL_MASK));
        crearRespaldo.setIcon(new javax.swing.ImageIcon(getClass().getResource("/gui/icono/respaldo_crear.png"))); // NOI18N
        crearRespaldo.setText("Crear respaldo de datos...");
        crearRespaldo.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                crearRespaldo(evt);
            }
        });
        respaldo.add(crearRespaldo);

        barraMenu.add(respaldo);

        setJMenuBar(barraMenu);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 554, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 339, Short.MAX_VALUE)
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void minimizarAN(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_minimizarAN
        if (SystemTray.isSupported())
        {
            barraNotificacion= SystemTray.getSystemTray();
            try {
                barraNotificacion.add(iconoBarraNotificacion);
                this.setVisible(false);
            } catch (AWTException ex) {JOptionPane.showMessageDialog(this, MINIMIZAR_AN_FALLO,
                    "Minimizar al área de notificación", JOptionPane.WARNING_MESSAGE);}
        }
        else
            JOptionPane.showMessageDialog(this, MINIMIZAR_AN_NO, "Minimizar al área de notificación",
                    JOptionPane.WARNING_MESSAGE);
    }//GEN-LAST:event_minimizarAN

    private void configuracion(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_configuracion
        try {
            if (nucleo.detener(false))
            {
                try {
                    String puertoRMI= nucleo.getPuertoRMI();
                    String interfaceRed= nucleo.getNombreInterfaceRed();
                    List<String> interfacesPc= nucleo.getInterfacesRed();
                    int tipoIP= nucleo.getTipoIP();
                    DialogoConfiguracion dc= new DialogoConfiguracion(puertoRMI, interfacesPc, interfaceRed,
                            tipoIP, nucleo);
                    if (dc.hacerVisible(this))
                    {
                        JOptionPane.showMessageDialog(this, REINICIAR, "Configuración", JOptionPane.WARNING_MESSAGE);
                        nucleo.quitarNucleoListener();
                        System.exit(0);
                    }
                    else
                        nucleo.iniciar();
                } catch (IOException ex) {this.nucleoEventoError(ex.getMessage());}
            }
            else
                JOptionPane.showMessageDialog(this, DETENER_NO, "Configurar puertos", JOptionPane.WARNING_MESSAGE);
        } catch (InterruptedException ex) {this.nucleoEventoError(ex.getMessage());}
          catch (SQLException ex) {this.nucleoEventoError(ex.getMessage());}
    }//GEN-LAST:event_configuracion

    private void acercaDe(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_acercaDe
        DialogoAcercaDe dad= new DialogoAcercaDe(Nucleo.obtenerVersionSistema(), Nucleo.obtenerFechaCompilacion(),
                Nucleo.obtenerVersionJVM());
        dad.hacerVisible(this);
    }//GEN-LAST:event_acercaDe

    private void salir(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_salir
        try {
            if (nucleo.detener(false))
            {
                nucleo.quitarNucleoListener();
                System.exit(0);
            }
            else
                JOptionPane.showMessageDialog(this, DETENER_NO, "Salir", JOptionPane.WARNING_MESSAGE);
        } catch (InterruptedException ex) {this.nucleoEventoError(ex.getMessage());}
          catch (SQLException ex) {this.nucleoEventoError(ex.getMessage());}
    }//GEN-LAST:event_salir

    private void cargarRespaldo(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cargarRespaldo
        String titulo= "Cargar respaldo de datos";
        String fin= "El respaldo de datos se ha cargado correctamente.";
        try {
            if (nucleo.detener(false))
            {
                FileFilter [] filtro= new FileFilter[1];
                filtro[0]= new FiltroZip();
                Selector selector= new Selector(filtro, titulo, false);
                File f= selector.hacerVisibleSelectorAbrir(this);
                if (f != null)
                {
                    DialogoRespaldo dr= new DialogoRespaldo(DialogoRespaldo.TIPO_CARGAR);
                    nucleo.cargarRespaldo(f, dr.obtenerDialogo());
                    dr.hacerVisible(this);
                    JOptionPane.showMessageDialog(this, fin, titulo, JOptionPane.INFORMATION_MESSAGE);
                }
                nucleo.iniciar();
            }
            else
                JOptionPane.showMessageDialog(this, DETENER_NO, titulo, JOptionPane.WARNING_MESSAGE);
        } catch (InterruptedException ex) {this.nucleoEventoError(ex.getMessage());}
          catch (SQLException ex) {this.nucleoEventoError(ex.getMessage());}
    }//GEN-LAST:event_cargarRespaldo

    private void crearRespaldo(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_crearRespaldo
        String titulo= "Crear respaldo de datos";
        String fin= "El respaldo de datos se ha creado correctamente.";
        try {
            if (nucleo.detener(false))
            {
                FileFilter [] filtro= new FileFilter[1];
                filtro[0]= new FiltroZip();
                Calendar c= Calendar.getInstance();
                String fechaHoy= this.corregirFecha(c.get(Calendar.DATE)) + "/" +
                        this.corregirFecha(c.get(Calendar.MONTH) + 1) + "/" + c.get(Calendar.YEAR);
                String nombreSugerido= "Respaldo_" + c.get(Calendar.YEAR) + this.corregirFecha(c.get(Calendar.MONTH) + 1) +
                        this.corregirFecha(c.get(Calendar.DATE));
                File archivoSugerido= new File(nombreSugerido);
                Selector selector= new Selector(filtro, titulo, false);
                selector.predefinir(archivoSugerido);
                File f= selector.hacerVisibleSelectorGuardar(this);
                if (f != null)
                {
                    DialogoRespaldo dr= new DialogoRespaldo(DialogoRespaldo.TIPO_CREAR);
                    nucleo.crearRespaldo(f, dr.obtenerDialogo());
                    dr.hacerVisible(this);
                    try {
                        nucleo.guardarFechaRespaldo(fechaHoy);
                        JOptionPane.showMessageDialog(this, fin, titulo, JOptionPane.INFORMATION_MESSAGE);
                    } catch (IOException ex) {this.nucleoEventoError(ex.getMessage());}
                }
                nucleo.iniciar();
            }
            else
                JOptionPane.showMessageDialog(this, DETENER_NO, titulo, JOptionPane.WARNING_MESSAGE);
        } catch (InterruptedException ex) {this.nucleoEventoError(ex.getMessage());}
          catch (SQLException ex) {this.nucleoEventoError(ex.getMessage());}
    }//GEN-LAST:event_crearRespaldo

    private void salirCruz(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_salirCruz
        this.salir(null);
    }//GEN-LAST:event_salirCruz

    private void abrir(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_abrir
        this.setVisible(true);
        this.toFront();
        barraNotificacion.remove(iconoBarraNotificacion);
        barraNotificacion= null;
    }//GEN-LAST:event_abrir

    private String corregirFecha(int valor)
    {
        if (valor < 10)
            return "0" + valor;
        else
            return String.valueOf(valor);
    }
    
    private void clickRaton(MouseEvent evt)
    {
        if (evt.getButton() == MouseEvent.BUTTON1 && evt.getClickCount() == 2)
            this.abrir(null);
    }
    
    private void cambiarToolTip(String nuevoEstado, String nuevaConexion)
    {
        String info= "Servidor - Estudio Jurídico\nEstado: " + nuevoEstado + "\nConexiones activas: " + nuevaConexion;
        iconoBarraNotificacion.setToolTip(info);
    }
    
    private void restaurarVentana()
    {
        if (this.getExtendedState() == javax.swing.JFrame.ICONIFIED)
        {
            this.setExtendedState(javax.swing.JFrame.NORMAL);
            this.setVisible(true);
            this.toFront();
        }
        if (barraNotificacion != null)
            this.abrir(null);
    }
    
    @Override
    public void nucleoEventoError(String mensaje) {
        GestorLog.escribirLog(mensaje);
        this.restaurarVentana();
        DialogoErrorGrave deg= new DialogoErrorGrave(mensaje);
        deg.hacerVisible(this);
        System.exit(-1);
    }

    @Override
    public void nucleoEventoActualizarGui(int elemento, String valor) {
        switch (elemento)
        {
            case Nucleo.ESTADO_FUNCIONANDO:
                pp.setEstado(valor, Color.green);
                this.cambiarToolTip(valor, pp.getConexionesActivas());
                break;
            case Nucleo.IP: pp.setDireccionIP(valor); break;
            case Nucleo.PUERTO_RMI: pp.setPuertoRMI(valor); break;
            case Nucleo.CONEXIONES:
                pp.setConexionesActivas(valor);
                this.cambiarToolTip(pp.getEstado(), valor);
                break;
            case Nucleo.MOTOR_BD: pp.setMotorBD(valor); break;
            case Nucleo.DRIVER_BD: pp.setVersionDriver(valor); break;
            case Nucleo.MODO_CONEXION: pp.setModoConexion(valor); break;
            case Nucleo.ULTIMO_RESPALDO: pp.setUltimoRespaldo(valor); break;
            case Nucleo.ESTADO_DETENIDO:
                pp.setEstado(valor, Color.red);
                this.cambiarToolTip(valor, pp.getConexionesActivas());
                break;
            case Nucleo.ESTADO_INICIANDO:
                pp.setEstado(valor, Color.green);
                this.cambiarToolTip(valor, pp.getConexionesActivas());
                break;
            case Nucleo.SEGUNDA_INSTANCIA:
                JOptionPane.showMessageDialog(this, valor, "Servidor", JOptionPane.WARNING_MESSAGE);
                System.exit(0);
                break;
            case Nucleo.PUERTO_RMI_OCUPADO:
                JOptionPane.showMessageDialog(this, valor, "Servicio RMI", JOptionPane.WARNING_MESSAGE);
                try {
                    String puertoRMI= nucleo.getPuertoRMI();
                    String interfaceRed= nucleo.getNombreInterfaceRed();
                    List<String> interfacesPc= nucleo.getInterfacesRed();
                    int tipoIP= nucleo.getTipoIP();
                    DialogoConfiguracion dc= new DialogoConfiguracion(puertoRMI, interfacesPc, interfaceRed, tipoIP,
                            nucleo);
                    if (dc.hacerVisible(this))
                        nucleo.iniciar();
                    else
                        System.exit(0);
                } catch (IOException ex) {this.nucleoEventoError(ex.getMessage());}
                break;
            case Nucleo.INTERFACE_RED: pp.setInterfaceRed(valor); break;
            case Nucleo.ERROR_INTERFAZ_RED:
                JOptionPane.showMessageDialog(this, valor, "Servidor", JOptionPane.WARNING_MESSAGE);
                try {
                    String puertoRMI= nucleo.getPuertoRMI();
                    List<String> interfacesPc= nucleo.getInterfacesRed();
                    int tipoIP= nucleo.getTipoIP();
                    DialogoConfiguracion dc= new DialogoConfiguracion(puertoRMI, interfacesPc, "", tipoIP, nucleo);
                    if (dc.hacerVisible(this))
                        nucleo.iniciar();
                    else
                        System.exit(0);
                } catch (IOException ex) {this.nucleoEventoError(ex.getMessage());}
                break;
        }
    }
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private java.awt.MenuItem abrir;
    private javax.swing.JMenuItem acercaDe;
    private javax.swing.JMenu archivo;
    private javax.swing.JMenuBar barraMenu;
    private javax.swing.JMenuItem cargarRespaldo;
    private javax.swing.JMenuItem configuracion;
    private javax.swing.JMenuItem crearRespaldo;
    private javax.swing.JPopupMenu.Separator jSeparator1;
    private javax.swing.JPopupMenu.Separator jSeparator2;
    private java.awt.PopupMenu menuBarraTray;
    private javax.swing.JMenuItem minimizarAN;
    private javax.swing.JMenu respaldo;
    private javax.swing.JMenuItem salir;
    // End of variables declaration//GEN-END:variables
}
